package com.bt.att.parser;

import com.bt.att.model.BillingPeriod;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * BillParserOld.
 *
 * @author Zakir Magdum
 */
public class BillParser {
    private static final Logger logger = LoggerFactory.getLogger(BillParser.class);
    private String fileName;
    private List<String> columns = new ArrayList<String>();
    //private List<List> data = new ArrayList<List>();
    private String currentUser;
    private String currentUserNumber;
    private boolean titleStarted;
    private List<String> currentValues;
    private boolean callDetailStarted;
    private BillEntryProcessor handler;
    public static DateFormat billingPeriodDateFormat = new SimpleDateFormat("MM/dd/yy");

    public BillParser(String fileName, BillEntryProcessor handler) {
        this.fileName = fileName;
        this.handler = handler;
    }

    public void parse() {
		FileInputStream fstream = null;
		BufferedReader br = null;
		try {
			fstream = new FileInputStream(fileName);
			br = new BufferedReader(new InputStreamReader(fstream));
			String strLine;

			while ((strLine = br.readLine()) != null) {
				processLine(strLine);
			}
			br.close();
			fstream.close();
		} catch (Exception e) {
			logger.error("Error: " + e.getMessage());
		} finally {
			try {
				if (br != null){
					br.close();
				}
				if (fstream != null){
					fstream.close();
				}
			} catch (Exception ee) {
				logger.error("Error in closing the stream: "
						+ ee.getMessage());
			}
		}
    }

    private void processLine(String line) {
        if (titleStarted) {
            if (line.contains("</tr>")) {
                titleStarted = false;
            } else {
                String tmp = getTdValue(line);
                if (StringUtils.isNotBlank(tmp)) {
                    columns.add(tmp);
                }
            }
        }
        if (currentValues != null) {
            if (line.contains("</tr>")) {
                if (StringUtils.isNotBlank(currentUser)) {
                    handler.handle(currentUser, currentUserNumber, columns, currentValues);
                }
                //data.add(currentValues);
                currentValues = null;
            } else {
                currentValues.add(getTdValue(line));
            }
        }

        if (callDetailStarted) {
            if (line.contains("</tr>")) {
                callDetailStarted = false;
            } else {
                if (StringUtils.isBlank(currentUserNumber)) {
                    currentUserNumber = getTdValue(getTdValue(line));
                }
            }
        }
        if (line.contains("<tr class=\"title\">") || line.contains("<tr class=\"row3130\">")) {
            titleStarted = true;
            columns.clear();
        } else if (line.contains("<tr class=\"rowclr\">")) {
            currentValues = new ArrayList<String>();
        } else if (line.contains("Call Detail") || line.contains("Data Detail")) {
            if (!line.trim().startsWith("<!--")) {
                callDetailStarted = true;
                currentUserNumber = "";
                currentUser = "";
            }
        } else if (line.contains("User Name")) {
            currentUser = getTdValue(line);
            int ii = currentUser.indexOf(":");
            if (ii > 0) {
                currentUser = currentUser.substring(ii+1);
            }
        } else if (line.contains("Statement Date")) {
            BillingPeriod bp = parseBillingPeriod(line);
            handler.handle(null, null,Arrays.asList(new String[] {"startDate", "endDate"}),
                    Arrays.asList(new String[] {billingPeriodDateFormat.format(bp.getStart()),
                            billingPeriodDateFormat.format(bp.getEnd())}));
        }

    }

    private String getTdValue(String line) {
        int ii = line.indexOf(">");
        if (ii > 0) {
            line = line.substring(ii+1);
        }
        ii = line.lastIndexOf("<");
        if (ii > 0) {
            line = line.substring(0, ii);
        }
        line = line.replaceAll("&nbsp;", "");
        line = line.replaceAll("<nobr>", "");
        line = line.replaceAll("</nobr>", "");
        line = line.replaceAll("<br>", "");
        line = line.replaceAll("</h2>", "");
        line = line.replaceAll("</h3>", "");
        line = line.replaceAll("<h3>", "");
        return line.trim();

    }

    private BillingPeriod parseBillingPeriod(String line) {
        // Statement Date : 10/02/11 - 11/01/11
        int ii = line.indexOf(":");
        String temp = line;
        if (ii > 0) {
            temp = line.substring(ii+1);
        }
        String[] tokens = temp.split("-");
        if (tokens.length > 1) {
            try {
                Date start = billingPeriodDateFormat.parse(tokens[0].trim());
                Date end = billingPeriodDateFormat.parse(tokens[1].trim());
                return new BillingPeriod(start, end);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        URL url = Thread.currentThread().getContextClassLoader().getResource("att-oct2011.html");

        try {
            BillParser parser = new BillParser(url.getFile(), new PrintBillEntry());
            parser.parse();
            System.out.println(parser.currentUser);
            System.out.println(parser.currentUserNumber);
            System.out.println(parser.columns);
//        for (List list : parser.data) {
//            System.out.println(list);
//        }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class PrintBillEntry implements BillEntryProcessor {

        @Override
        public void handle(String currentUser, String currentUserNumber, List<String> columns, List<String> values) {
            if (columns.size() > values.size()) {
                System.out.println("Columns " + columns.size() + " Values " + values.size());
                System.out.println(columns);
                System.out.println(values);
            }
            StringBuilder bldr = new StringBuilder();
            bldr.append("User=");
            bldr.append(currentUser);
            bldr.append(", ");
            bldr.append("UserNumber=");
            bldr.append(currentUserNumber);
            bldr.append(", ");

            for (int ii=0; ii < columns.size(); ii++) {
                bldr.append(columns.get(ii));
                bldr.append("=");
                bldr.append(values.get(ii));
                bldr.append(", ");
            }
            System.out.println(bldr.toString());
        }
    }
}
